package cn.chiship.framework.business.biz.cashier.service.impl;

import cn.chiship.framework.business.biz.cashier.entity.*;
import cn.chiship.framework.business.biz.cashier.enums.OrderStatusEnum;
import cn.chiship.framework.business.biz.cashier.enums.OrderTypeEnum;
import cn.chiship.framework.business.biz.cashier.mapper.BusinessOrderPaymentRecordMapper;
import cn.chiship.framework.business.biz.cashier.pojo.dto.OrderProductCreateDto;
import cn.chiship.framework.business.biz.cashier.pojo.dto.OrderRechargeCreateDto;
import cn.chiship.framework.business.biz.cashier.service.BusinessOrderHeaderItemService;
import cn.chiship.framework.business.biz.product.entity.Product;
import cn.chiship.framework.business.biz.product.mapper.ProductMapper;
import cn.chiship.framework.common.constants.CommonCacheConstants;
import cn.chiship.framework.common.properties.FrameworkProperties;
import cn.chiship.framework.common.util.CodeGenerationUtil;
import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.framework.business.biz.cashier.mapper.BusinessOrderHeaderMapper;
import cn.chiship.framework.business.biz.cashier.service.BusinessOrderHeaderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 订单主表业务接口实现层 2023/3/26
 *
 * @author lijian
 */
@Service
public class BusinessOrderHeaderServiceImpl extends BaseServiceImpl<BusinessOrderHeader, BusinessOrderHeaderExample>
        implements BusinessOrderHeaderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(BusinessOrderHeaderServiceImpl.class);

    @Resource
    BusinessOrderHeaderMapper businessOrderHeaderMapper;

    @Resource
    BusinessOrderHeaderItemService businessOrderHeaderItemService;

    @Resource
    BusinessOrderPaymentRecordMapper businessOrderPaymentRecordMapper;

    @Resource
    ProductMapper productMapper;

    @Resource
    RedisService redisService;

    @Resource
    FrameworkProperties frameworkProperties;

    @Override
    public BaseResult createOrder(OrderRechargeCreateDto orderRechargeCreateDto, CacheUserVO cacheUserVO) {
        Long begin = 0L;
        String noSuffix = businessOrderHeaderMapper.getNoSuffix();
        if (!StringUtil.isNullOrEmpty(noSuffix)) {
            begin = Long.valueOf(noSuffix);
        }
        BusinessOrderHeader orderHeader = new BusinessOrderHeader();
        orderHeader.setId(CodeGenerationUtil.generateOrderId(begin + 1));
        orderHeader.setGmtCreated(System.currentTimeMillis());
        orderHeader.setGmtModified(System.currentTimeMillis());
        orderHeader.setIsDeleted(Byte.valueOf("0"));
        orderHeader.setOrderDate(System.currentTimeMillis());
        orderHeader.setOrderStatus(OrderStatusEnum.ORDER_STATUS_WAIT_PAY.getStatus());
        orderHeader.setCreatedBy(StringUtil.getString(cacheUserVO.getId()));
        orderHeader.setCreatedName(cacheUserVO.getRealName());
        orderHeader.setUserRealName(cacheUserVO.getRealName());
        orderHeader.setUserPhone(cacheUserVO.getMobile());
        orderHeader.setUserId(StringUtil.getString(cacheUserVO.getId()));
        orderHeader.setOrderType(OrderTypeEnum.ORDER_TYPE_RECHARGE.getType());

        orderHeader.setOrderName("[充值]" + orderRechargeCreateDto.getOrderName());
        orderHeader.setGrandTotal(new BigDecimal(orderRechargeCreateDto.getPrice()));
        orderHeader.setRefundTotal(BigDecimal.ZERO);
        orderHeader.setOpenId(orderRechargeCreateDto.getOpenId());

        String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_TIMEOUT_CLOSED_ORDER_PREFIX) + ":"
                + orderHeader.getId();
        Long closedTime = orderHeader.getOrderDate() + frameworkProperties.getOrderTimeout() * 60 * 1000;
        redisService.set(key, closedTime, frameworkProperties.getOrderTimeout() * 60);

        saveOrderStatus(orderHeader.getId(), OrderStatusEnum.ORDER_STATUS_WAIT_PAY);

        super.insertSelective(orderHeader);

        return BaseResult.ok(orderHeader.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult createOrder(OrderProductCreateDto orderProductCreateDto, CacheUserVO cacheUserVO) {
        String productId = orderProductCreateDto.getProductId();
        Integer productNumber = orderProductCreateDto.getProductNumber();
        Product product = productMapper.selectByPrimaryKey(productId);
        if (StringUtil.isNull(product)) {
            return BaseResult.error("无效的商品标识");
        }
        if (productNumber > product.getTotalInventory() || productNumber < 1) {
            return BaseResult.error("购买数量不规范");
        }

        Long begin = 0L;
        String noSuffix = businessOrderHeaderMapper.getNoSuffix();
        if (!StringUtil.isNullOrEmpty(noSuffix)) {
            begin = Long.valueOf(noSuffix);
        }
        BusinessOrderHeader orderHeader = new BusinessOrderHeader();
        orderHeader.setId(CodeGenerationUtil.generateOrderId(begin + 1));
        orderHeader.setGmtCreated(System.currentTimeMillis());
        orderHeader.setGmtModified(System.currentTimeMillis());
        orderHeader.setIsDeleted(Byte.valueOf("0"));
        orderHeader.setOrderDate(System.currentTimeMillis());
        orderHeader.setOrderStatus(OrderStatusEnum.ORDER_STATUS_WAIT_PAY.getStatus());
        orderHeader.setCreatedBy(StringUtil.getString(cacheUserVO.getId()));
        orderHeader.setCreatedName(cacheUserVO.getRealName());
        orderHeader.setUserRealName(cacheUserVO.getRealName());
        orderHeader.setUserPhone(cacheUserVO.getMobile());
        orderHeader.setUserId(StringUtil.getString(cacheUserVO.getId()));
        orderHeader.setOrderType(OrderTypeEnum.ORDER_TYPE_PRODUCT.getType());

        orderHeader.setOpenId(orderProductCreateDto.getOpenId());

        orderHeader.setOrderName("[商品]" + product.getName());
        orderHeader.setGrandTotal(new BigDecimal(productNumber).multiply(product.getPrice()));
        orderHeader.setRefundTotal(BigDecimal.ZERO);

        BusinessOrderHeaderItem orderHeaderItem = new BusinessOrderHeaderItem();
        orderHeaderItem.setOrderNo(orderHeader.getId());
        orderHeaderItem.setProductId(productId);
        orderHeaderItem.setProductName(product.getName());
        orderHeaderItem.setProductImage(product.getSmallImage());
        orderHeaderItem.setProductPrice(product.getPrice());
        orderHeaderItem.setProductNumber(Long.valueOf(productNumber));
        orderHeaderItem.setItemType(Byte.valueOf("0"));
        businessOrderHeaderItemService.insertSelective(orderHeaderItem);

        //此地方应该减库存，订单超时关闭+库存，支付失败+库存  业务逻辑暂时保留

        String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_TIMEOUT_CLOSED_ORDER_PREFIX) + ":"
                + orderHeader.getId();
        Long closedTime = orderHeader.getOrderDate() + frameworkProperties.getOrderTimeout() * 60 * 1000;
        redisService.set(key, closedTime, frameworkProperties.getOrderTimeout() * 60);

        saveOrderStatus(orderHeader.getId(), OrderStatusEnum.ORDER_STATUS_WAIT_PAY);

        super.insertSelective(orderHeader);

        return BaseResult.ok(orderHeader.getId());
    }

    @Override
    public BaseResult getOrderStatusByOrderId(String orderId) {
        String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_ORDER_STATUS_PREFIX);
        if (redisService.hHasKey(key, orderId)) {
            return BaseResult.ok(redisService.hget(key, orderId));
        } else {
            BusinessOrderHeader orderHeader = super.selectByPrimaryKey(orderId);
            if (StringUtil.isNull(orderHeader)) {
                return BaseResult.error("查无订单数据！");
            }
            OrderStatusEnum orderStatusEnum = OrderStatusEnum.getOrderStatusEnum(orderHeader.getOrderStatus());
            return saveOrderStatus(orderId, orderStatusEnum);
        }

    }

    @Override
    public BusinessOrderHeader selectByPrimaryKey(Object id) {
        BusinessOrderHeader orderHeader = super.selectByPrimaryKey(id);
        if (!ObjectUtil.isEmpty(orderHeader)) {
            if (StringUtil.isNull(orderHeader.getClosedTime())) {
                String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_TIMEOUT_CLOSED_ORDER_PREFIX) + ":"
                        + orderHeader.getId();
                if (redisService.hasKey(key)) {
                    orderHeader.setClosedTime((Long) redisService.get(key));
                }
            }

        }
        return orderHeader;
    }

    @Override
    public BaseResult selectDetailsByPrimaryKey(Object id) {
        Map<String, Object> result = new HashMap<>(2);
        BusinessOrderHeader orderHeader = businessOrderHeaderMapper.selectByPrimaryKey(id);
        result.put("orderHeader", orderHeader);
        BusinessOrderPaymentRecordExample businessOrderPaymentRecordExample = new BusinessOrderPaymentRecordExample();
        businessOrderPaymentRecordExample.createCriteria().andOrderIdEqualTo(StringUtil.getString(id));
        List<BusinessOrderPaymentRecord> businessOrderPaymentRecords = businessOrderPaymentRecordMapper
                .selectByExample(businessOrderPaymentRecordExample);
        BusinessOrderPaymentRecord businessOrderPaymentRecord = new BusinessOrderPaymentRecord();
        if (!businessOrderPaymentRecords.isEmpty()) {
            businessOrderPaymentRecord = businessOrderPaymentRecords.get(0);
        }
        result.put("paymentRecord", businessOrderPaymentRecord);

        BusinessOrderHeaderItemExample businessOrderHeaderItemExample = new BusinessOrderHeaderItemExample();
        businessOrderHeaderItemExample.createCriteria().andOrderNoEqualTo(orderHeader.getId());
        List<BusinessOrderHeaderItem> businessOrderHeaderItems = businessOrderHeaderItemService.selectByExample(businessOrderHeaderItemExample);
        result.put("headerItems", businessOrderHeaderItems);
        return BaseResult.ok(result);
    }

    @Override
    public BaseResult closedOrder(String orderNo) {
        BusinessOrderHeader orderHeader = selectByPrimaryKey(orderNo);
        if (ObjectUtil.isEmpty(orderHeader)) {
            return BaseResult.error("无效的订单！");
        }
        orderHeader.setOrderStatus(OrderStatusEnum.ORDER_STATUS_CLOSE.getStatus());
        orderHeader.setClosedTime(System.currentTimeMillis());
        super.updateByPrimaryKeySelective(orderHeader);
        saveOrderStatus(orderNo, OrderStatusEnum.ORDER_STATUS_CLOSE);
        return BaseResult.ok();
    }

    /**
     * 保存订单状态
     *
     * @param orderNo
     * @param orderStatusEnum
     */
    private BaseResult saveOrderStatus(String orderNo, OrderStatusEnum orderStatusEnum) {
        String key = CommonCacheConstants.buildKey(CommonCacheConstants.REDIS_ORDER_STATUS_PREFIX);
        Map<String, Object> status = new HashMap<>(7);
        status.put("status", orderStatusEnum.getStatus());
        status.put("message", orderStatusEnum.getMessage());
        redisService.hset(key, orderNo, status);
        return BaseResult.ok(status);
    }

}
